use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet, BinaryHeap};
use std::cmp::Ordering;
use chrono::{DateTime, Utc};
use uuid::Uuid;
use crate::path_planner::PathPlanner;

/// 展馆主题枚举
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Theme {
    AntiWarHistory,    // 抗战历史
    RevolutionaryFigures, // 革命人物
    CulturalHeritage,  // 文化遗产
}

/// 展馆结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Museum {
    pub id: String,
    pub name: String,
    pub position: (i32, i32), // 网格坐标 (x, y)
    pub themes: Vec<f64>,     // 主题分布向量 [p1, p2, p3]
    pub dominant_theme: Theme, // 主导主题
    pub composite_key: String, // 复合键
    pub crowd_level: i32,     // 人流量
}

/// 边权值结构
#[derive(Debug, Clone)]
pub struct EdgeWeight {
    pub from: String,
    pub to: String,
    pub weight: f64,
    pub updated_weight: f64,
}

/// 用户行为数据
#[derive(Debug, Clone)]
pub struct UserBehavior {
    pub user_id: String,
    pub stay_time: HashMap<String, f64>, // 展馆ID -> 停留时间
    pub click_count: HashMap<String, i32>, // 展馆ID -> 点击次数
    pub theme_preference: Vec<f64>, // 用户主题偏好向量
}

/// 设备状态
#[derive(Debug, Clone)]
pub struct DeviceStatus {
    pub device_id: String,
    pub cpu_usage: f64,    // CPU使用率 (0.0-1.0)
    pub memory_available: f64, // 可用内存 (GB)
    pub latency: f64,      // 网络延迟 (ms)
    pub capability: f64,   // 计算能力
}

/// 博物馆系统主类
pub struct MuseumSystem {
    museums: HashMap<String, Museum>,
    edge_weights: HashMap<String, EdgeWeight>,
    user_behaviors: HashMap<String, UserBehavior>,
    device_statuses: HashMap<String, DeviceStatus>,
    path_cache: HashMap<String, Vec<String>>,
    path_planner: PathPlanner,
}

impl MuseumSystem {
    pub fn new() -> Self {
        let mut system = MuseumSystem {
            museums: HashMap::new(),
            edge_weights: HashMap::new(),
            user_behaviors: HashMap::new(),
            device_statuses: HashMap::new(),
            path_cache: HashMap::new(),
            path_planner: PathPlanner::new(),
        };
        
        // 初始化示例数据
        system.initialize_sample_data();
        system
    }

    /// 初始化示例数据
    fn initialize_sample_data(&mut self) {
        // 创建示例展馆
        let museums_data = vec![
            ("V1", "湖北省博物馆", (3, 5), vec![0.1, 0.7, 0.2], 5),
            ("V2", "革命纪念馆", (4, 6), vec![0.8, 0.1, 0.1], 8),
            ("V3", "文化遗产馆", (5, 4), vec![0.2, 0.1, 0.7], 12),
            ("V4", "抗战历史馆", (6, 7), vec![0.9, 0.05, 0.05], 15),
            ("V5", "英雄事迹馆", (7, 5), vec![0.1, 0.8, 0.1], 3),
        ];

        for (id, name, pos, themes, crowd) in museums_data {
            let museum = self.create_museum(id, name, pos, themes, crowd);
            self.museums.insert(id.to_string(), museum);
        }

        // 初始化设备状态
        self.initialize_device_statuses();
    }

    /// 创建展馆
    fn create_museum(&self, id: &str, name: &str, position: (i32, i32), themes: Vec<f64>, crowd_level: i32) -> Museum {
        // 步骤1(1): 计算主导主题 - 使用公式 argmax(p_k)
        let dominant_theme = self.calculate_dominant_theme(&themes);
        
        // 步骤1(2): 生成复合键 - 使用公式 Key_i = G_{x,y}-T_k-argmax(p_k)
        let composite_key = self.generate_composite_key(position, 2, &dominant_theme);
        
        Museum {
            id: id.to_string(),
            name: name.to_string(),
            position,
            themes,
            dominant_theme,
            composite_key,
            crowd_level,
        }
    }

    /// 步骤1(1): 计算主导主题
    /// 公式: argmax_{1≤k≤K} max_{p_k}
    fn calculate_dominant_theme(&self, themes: &[f64]) -> Theme {
        let max_index = themes.iter()
            .enumerate()
            .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Equal))
            .map(|(index, _)| index)
            .unwrap_or(0);
        
        match max_index {
            0 => Theme::AntiWarHistory,
            1 => Theme::RevolutionaryFigures,
            2 => Theme::CulturalHeritage,
            _ => Theme::AntiWarHistory,
        }
    }

    /// 步骤1(2): 生成复合键
    /// 公式: Key_i = G_{x,y}-T_k-argmax(p_k)
    fn generate_composite_key(&self, position: (i32, i32), time_slot: i32, theme: &Theme) -> String {
        let theme_str = match theme {
            Theme::AntiWarHistory => "1",
            Theme::RevolutionaryFigures => "2", 
            Theme::CulturalHeritage => "3",
        };
        format!("G_{},{}-T_{}-{}", position.0, position.1, time_slot, theme_str)
    }

    /// 步骤1(3): 计算边权值
    /// 公式: E_{ij} = α·sim(T_i,T_j) + β(1-D_{ij}/D_max) + λ·e^(-λ·t_crowd)
    pub fn calculate_edge_weights(&mut self) {
        println!("\n=== 步骤1(3): 计算边权值 ===");
        
        let alpha = 0.4; // 主题相似度权重
        let beta = 0.4;  // 空间衰减权重
        let lambda = 0.2; // 时间衰减权重
        let d_max = 100.0; // 最大可接受距离
        
        let museum_ids: Vec<String> = self.museums.keys().cloned().collect();
        
        for i in 0..museum_ids.len() {
            for j in i+1..museum_ids.len() {
                let from_id = &museum_ids[i];
                let to_id = &museum_ids[j];
                
                let from_museum = &self.museums[from_id];
                let to_museum = &self.museums[to_id];
                
                // 计算主题相似度 sim(T_i, T_j)
                let theme_similarity = self.calculate_theme_similarity(&from_museum.themes, &to_museum.themes);
                
                // 计算空间距离 D_{ij}
                let distance = self.calculate_distance(from_museum.position, to_museum.position);
                
                // 计算空间衰减 1-D_{ij}/D_max
                let spatial_decay = 1.0 - distance / d_max;
                
                // 计算时间衰减 e^(-λ·t_crowd)
                let time_decay = (-lambda * to_museum.crowd_level as f64).exp();
                
                // 计算总边权值
                let weight = alpha * theme_similarity + beta * spatial_decay + lambda * time_decay;
                
                let edge_key = format!("{}->{}", from_id, to_id);
                let edge_weight = EdgeWeight {
                    from: from_id.clone(),
                    to: to_id.clone(),
                    weight,
                    updated_weight: weight,
                };
                
                self.edge_weights.insert(edge_key, edge_weight);
                
                println!("边权值 {}->{}: {:.4} (主题相似度: {:.4}, 空间衰减: {:.4}, 时间衰减: {:.4})", 
                    from_id, to_id, weight, theme_similarity, spatial_decay, time_decay);
            }
        }
    }

    /// 计算主题相似度
    fn calculate_theme_similarity(&self, themes1: &[f64], themes2: &[f64]) -> f64 {
        let min_len = themes1.len().min(themes2.len());
        let mut dot_product = 0.0;
        let mut norm1 = 0.0;
        let mut norm2 = 0.0;
        
        for i in 0..min_len {
            dot_product += themes1[i] * themes2[i];
            norm1 += themes1[i] * themes1[i];
            norm2 += themes2[i] * themes2[i];
        }
        
        if norm1 == 0.0 || norm2 == 0.0 {
            return 0.0;
        }
        
        dot_product / (norm1.sqrt() * norm2.sqrt())
    }

    /// 计算欧几里得距离
    fn calculate_distance(&self, pos1: (i32, i32), pos2: (i32, i32)) -> f64 {
        let dx = (pos1.0 - pos2.0) as f64;
        let dy = (pos1.1 - pos2.1) as f64;
        (dx * dx + dy * dy).sqrt()
    }

    /// 步骤2: 分片策略
    /// 公式: Assign(S_{G_{x,y},T_k}) = argmin_{Node_j}(∑CPU_{Node_j})
    pub fn implement_sharding_strategy(&self) {
        println!("\n=== 步骤2: 分片策略 ===");
        
        let max_shard_size = 500; // N_max = 500
        let mut shards: HashMap<String, Vec<String>> = HashMap::new();
        
        // 按地理位置和时间槽分片
        for museum in self.museums.values() {
            let shard_key = format!("G_{},{}-T_2", museum.position.0, museum.position.1);
            shards.entry(shard_key).or_insert_with(Vec::new).push(museum.id.clone());
        }
        
        // 检查分片大小并分配CPU
        for (shard_key, museums) in shards {
            println!("分片 {}: {} 个展馆", shard_key, museums.len());
            
            if museums.len() > max_shard_size {
                println!("  分片过大，需要拆分");
                // 这里可以实现更复杂的分片逻辑
            }
            
            // 找到CPU使用率最低的节点
            let best_node = self.find_least_cpu_node();
            println!("  分配给节点: {}", best_node);
        }
    }

    /// 找到CPU使用率最低的节点
    fn find_least_cpu_node(&self) -> String {
        self.device_statuses.iter()
            .min_by(|(_, a), (_, b)| a.cpu_usage.partial_cmp(&b.cpu_usage).unwrap_or(Ordering::Equal))
            .map(|(id, _)| id.clone())
            .unwrap_or_else(|| "Node1".to_string())
    }

    /// 步骤3: 路径规划
    pub fn plan_optimal_path(&mut self, start_id: &str, goal_id: &str) -> Vec<String> {
        println!("\n=== 步骤3: 路径规划 ===");
        println!("从 {} 到 {} 的最优路径:", start_id, goal_id);
        
        // 使用A*算法进行路径规划
        let path = self.path_planner.find_path(
            start_id,
            goal_id,
            &self.museums,
            &self.edge_weights,
        );
        
        if let Some(path) = path {
            println!("最优路径: {}", path.join(" -> "));
            path
        } else {
            println!("未找到路径");
            vec![]
        }
    }

    /// 步骤4: 展馆检索
    pub fn search_museums(&self, grid_pos: (i32, i32), time_slot: i32, theme: &Theme) -> Vec<String> {
        println!("\n=== 步骤4: 展馆检索 ===");
        println!("查询条件: 网格位置{:?}, 时间槽{}, 主题{:?}", grid_pos, time_slot, theme);
        
        let mut results = Vec::new();
        
        for museum in self.museums.values() {
            // 检查网格位置
            if museum.position != grid_pos {
                continue;
            }
            
            // 检查主题匹配
            if museum.dominant_theme != *theme {
                continue;
            }
            
            // 检查人流量（排除动态惩罚项排除的展馆）
            if museum.crowd_level >= 15 {
                continue;
            }
            
            results.push(museum.id.clone());
        }
        
        println!("检索结果: {:?}", results);
        results
    }

    /// 步骤5: 路径缓存
    pub fn cache_path(&mut self, query_key: &str, path: Vec<String>) {
        println!("\n=== 步骤5: 路径缓存 ===");
        println!("缓存路径: {} -> {}", query_key, path.join(" -> "));
        
        self.path_cache.insert(query_key.to_string(), path);
    }

    pub fn get_cached_path(&self, query_key: &str) -> Option<Vec<String>> {
        self.path_cache.get(query_key).cloned()
    }

    /// 步骤6: 用户兴趣权重调整
    pub fn adjust_user_interest_weights(&mut self, user_id: &str) {
        println!("\n=== 步骤6: 用户兴趣权重调整 ===");
        
        if let Some(behavior) = self.user_behaviors.get(user_id) {
            // 计算总停留时间和总点击次数
            let total_stay_time: f64 = behavior.stay_time.values().sum();
            let total_clicks: i32 = behavior.click_count.values().sum();
            
            // 收集需要更新的边权值信息
            let mut updates = Vec::new();
            
            for (museum_id, stay_time) in &behavior.stay_time {
                let click_count = behavior.click_count.get(museum_id).unwrap_or(&0);
                
                // 公式: λ = 0.4·(t_stay/t_total) + 0.3·(∑H_click/A_total) + 0.3·sim(T_current, T_user)
                let time_weight = 0.4 * (stay_time / total_stay_time);
                let click_weight = 0.3 * (*click_count as f64 / total_clicks as f64);
                
                let museum = &self.museums[museum_id];
                let theme_similarity = self.calculate_theme_similarity(&museum.themes, &behavior.theme_preference);
                let theme_weight = 0.3 * theme_similarity;
                
                let interest_weight = time_weight + click_weight + theme_weight;
                
                println!("展馆 {} 兴趣权重: {:.4} (时间: {:.4}, 点击: {:.4}, 主题: {:.4})", 
                    museum_id, interest_weight, time_weight, click_weight, theme_weight);
                
                updates.push((museum_id.clone(), interest_weight));
            }
            
            // 更新边权值
            for (museum_id, interest_weight) in updates {
                self.update_edge_weights_with_interest(&museum_id, interest_weight);
            }
            
            // 更新用户主题偏好
            self.update_user_theme_preference(user_id);
        }
    }

    /// 更新边权值
    /// 公式: E'_{ij} = E_{ij} × (1 + λ_average · sim(T_i, T_j))
    fn update_edge_weights_with_interest(&mut self, museum_id: &str, interest_weight: f64) {
        let mut edge_updates = Vec::new();
        
        // 收集需要更新的边
        for edge in self.edge_weights.values() {
            if edge.from == museum_id || edge.to == museum_id {
                let other_id = if edge.from == museum_id { &edge.to } else { &edge.from };
                let other_museum = &self.museums[other_id];
                let current_museum = &self.museums[museum_id];
                
                let theme_similarity = self.calculate_theme_similarity(&current_museum.themes, &other_museum.themes);
                let lambda_average = interest_weight / 2.0; // 简化计算
                
                let new_weight = edge.weight * (1.0 + lambda_average * theme_similarity);
                edge_updates.push((edge.from.clone(), edge.to.clone(), new_weight));
            }
        }
        
        // 应用更新
        for (from, to, new_weight) in edge_updates {
            if let Some(edge) = self.edge_weights.get_mut(&format!("{}->{}", from, to)) {
                edge.updated_weight = new_weight;
                println!("更新边权值 {}->{}: {:.4} -> {:.4}", 
                    edge.from, edge.to, edge.weight, edge.updated_weight);
            }
        }
    }

    /// 更新用户主题偏好
    /// 公式: T_user^(t) = α·T_user^(t-1) + (1-α)·T_current
    fn update_user_theme_preference(&mut self, user_id: &str) {
        if let Some(behavior) = self.user_behaviors.get_mut(user_id) {
            let alpha = 0.8; // 历史兴趣衰减因子
            
            // 计算当前路径的主题向量（简化处理）
            let current_theme = vec![0.85, 0.15]; // 示例值
            
            for i in 0..behavior.theme_preference.len().min(current_theme.len()) {
                behavior.theme_preference[i] = alpha * behavior.theme_preference[i] + 
                                             (1.0 - alpha) * current_theme[i];
            }
            
            println!("更新用户主题偏好: {:?}", behavior.theme_preference);
        }
    }

    /// 步骤7: 设备状态检查和任务分配
    pub fn check_device_status_and_allocate_tasks(&mut self) {
        println!("\n=== 步骤7: 设备状态检查和任务分配 ===");
        
        // 计算各设备能力
        for (device_id, status) in &mut self.device_statuses {
            // 公式: Capability = (CPU_free/CPU_total) × RAM_available × (1/Latency)
            status.capability = ((1.0 - status.cpu_usage) * status.memory_available) / status.latency;
            
            println!("设备 {}: CPU使用率 {:.1}%, 可用内存 {:.1}GB, 延迟 {:.1}ms, 计算能力 {:.4}", 
                device_id, status.cpu_usage * 100.0, status.memory_available, status.latency, status.capability);
        }
        
        // 任务分配决策
        let threshold = 0.1; // θ = 0.1
        
        for (device_id, status) in &self.device_statuses {
            if status.capability >= threshold {
                println!("设备 {} 本地执行任务", device_id);
            } else {
                println!("设备 {} 任务卸载到边缘节点或云端", device_id);
            }
        }
    }

    /// 初始化设备状态
    fn initialize_device_statuses(&mut self) {
        let devices = vec![
            ("移动端", 0.6, 0.5, 100.0), // CPU使用率60%, 内存0.5GB, 延迟100ms
            ("边缘节点", 0.3, 4.0, 10.0), // CPU使用率30%, 内存4GB, 延迟10ms
            ("云端", 0.6, 16.0, 50.0),   // CPU使用率60%, 内存16GB, 延迟50ms
        ];
        
        for (id, cpu_usage, memory, latency) in devices {
            self.device_statuses.insert(id.to_string(), DeviceStatus {
                device_id: id.to_string(),
                cpu_usage,
                memory_available: memory,
                latency,
                capability: 0.0,
            });
        }
    }

    /// 运行系统演示
    pub fn run_demo(&mut self) {
        println!("开始系统演示...");
        
        // 步骤1: 计算边权值
        self.calculate_edge_weights();
        
        // 步骤2: 分片策略
        self.implement_sharding_strategy();
        
        // 步骤3: 路径规划
        let path = self.plan_optimal_path("V1", "V5");
        
        // 步骤4: 展馆检索
        let _search_results = self.search_museums((3, 5), 2, &Theme::RevolutionaryFigures);
        
        // 步骤5: 路径缓存
        if !path.is_empty() {
            self.cache_path("V1->V5", path.clone());
        }
        
        // 步骤6: 用户兴趣权重调整
        self.initialize_user_behavior("user1");
        self.adjust_user_interest_weights("user1");
        
        // 步骤7: 设备状态检查
        self.check_device_status_and_allocate_tasks();
        
        println!("\n系统演示完成！");
    }

    /// 初始化用户行为数据
    pub fn initialize_user_behavior(&mut self, user_id: &str) {
        let mut behavior = UserBehavior {
            user_id: user_id.to_string(),
            stay_time: HashMap::new(),
            click_count: HashMap::new(),
            theme_preference: vec![0.8, 0.2], // 初始主题偏好
        };
        
        // 添加示例数据
        behavior.stay_time.insert("V1".to_string(), 150.0);
        behavior.stay_time.insert("V2".to_string(), 200.0);
        behavior.click_count.insert("V1".to_string(), 5);
        behavior.click_count.insert("V2".to_string(), 3);
        
        self.user_behaviors.insert(user_id.to_string(), behavior);
    }
} 